package yawning.mew.cat;

import yawning.mew.ProcEffect.Trigger;
import yawning.mew.cat.CatModelSimulation.SimulatorProperty;
import yawning.mew.character.CharacterModel.AttackResult;
import yawning.mew.character.Druid.Glyph;
import yawning.mew.sim.SimulationAction;

public class FerociousBiteAction implements SimulationAction {
	CatModelSimState mState;

	FerociousBiteAction(CatModelSimState state) {
		mState = state;
	}

	public double perform() {
		int cost = mState.getEnergyCost(mState.mModel.biteCost);
		if ((mState.getEnergy() < cost && !mState.isOoCUp()) || mState.getComboPoints() == 0) return SimulationAction.ACTION_FAIL;

		double pBonusCrit = 0;
		if (mState.mSimUtil.getConfig().getBool(SimulatorProperty.ASSUMEEXTERNALBLEED) || mState.rakeEv.isUp() || mState.ripEv.isUp()) {
			pBonusCrit = mState.mModel.pBonusBiteCrit;
		}

		AttackResult result = mState.mModel.getYellowResult(pBonusCrit);

		if (mState.mDebug) mState.DBGF("Ferocious Bite (%s)", result);

		if (result == AttackResult.MISS) {
			cost = (int) Math.round(cost * 0.2);
			mState.nrBiteMiss++;
		} else if (result == AttackResult.DODGE) {
			cost = (int) Math.round(cost * 0.2);
			mState.nrBiteDodge++;
		} else {
			double damage = mState.mModel.levelDep.getFBBaseDmg() + mState.mModel.levelDep.getFBCpDmg() * mState.mComboPoints + mState.mModel.getAttackPower() * mState.mModel.levelDep.getFBCoeff() * mState.mComboPoints;

			// Handle the extra energy conversion mechanic.
			if (!mState.mModel.druid.hasGlyph(Glyph.FEROCIOUSBITE)) {
				int baseCost = (mState.oocEv.isUp()) ? 0 : cost;
				int extraEnergy = Math.min(mState.mModel.biteCost, mState.energyTickEv.mEnergy - baseCost);

				mState.energyTickEv.mEnergy -= extraEnergy;	// Subtract extra energy here.
				damage *= 1.0 + (double) extraEnergy / mState.mModel.biteCost;
			}

			if (result == AttackResult.CRIT) {
				mState.nrBiteCrit++;
				damage *= mState.mModel.multCrit;
				mState.mSimUtil.triggerProc(Trigger.YELLOWCRIT);
			} else {
				mState.nrBiteHit++;
				mState.mSimUtil.triggerProc(Trigger.YELLOW);
			}

			damage *= mState.mModel.multBiteFeralAggression;
			damage *= mState.getDirectDamageMult();
			mState.biteDamage += Math.round(damage);

			if (mState.mDebug) mState.DBGF("  Damage: %d", Math.round(damage));

			// Handle Blood in the Water
			if (mState.ripEv.isUp() && mState.isInBloodInTheWaterRange() && mState.mModel.pBloodInTheWater > 0.0) {
				mState.ripEv.onBite();
			}

			mState.mComboPoints = 0;
		}

		mState.onOoCConsumer(cost);
		return 1.0f;
	}
}
